NOTE
1.1 make vs new
What make and new are in Go, why memory allocation is needed, how they are used, their differences, and their implementation details.
This is a historical learning note and may contain outdated or incomplete understanding.
1. What They Are
Go built-in functions.
2. Why They Are Needed
Allocate memory space.
Value types can be used after declaration.
func TestVars(t *testing.T) {
var i int
var s string
fmt.Println(i, s)
}
// output
0
Reference types need memory space to be allocated.
func TestVars2(t *testing.T) {
var i *int
fmt.Println(i)
fmt.Println(*i)
}
// output
<nil>
--- FAIL: TestVars2 (0.00s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x0 pc=0x5098cf]
3. Usage
3.1. new
Allocate a block of memory, set it to the zero value, and return a pointer to the memory address for that type.
func TestNew(t *testing.T) {
var i *int
i = new(int)
fmt.Println(*i)
}
// output
0
3.1.1. Equivalent to &struct{}
type Stu struct {
// name
name string
}
func testNew() {
f := new(Stu) // actually *f = &Stu{}, so new is generally not used
f.TestPrintName()
f.SetName("user")
f.TestPrintName()
}
3.2. make
Used to create slices, maps, and channels. It allocates a block of memory and initializes it rather than setting it to the zero value (the zero value of these reference types is nil). It returns the value itself instead of a pointer (because slices, maps, and channels are reference types, so there is no need to return pointers to them).
func TestMake(t *testing.T) {
fmt.Println(makeSlice())
}
func makeSlice() []int {
return make([]int, 0)
}
4. new vs make
| make | new | |
|---|---|---|
| Purpose | Allocate heap memory | Allocate heap memory |
| Argument | Used to initialize slices, maps, and channels | Used to allocate memory for a type and set the memory to its zero value |
| Return | The three reference types themselves | A pointer to the type |
5. Implementation
5.1. new
func TestNew(t *testing.T) {
var i *int
i = new(int)
fmt.Println(*i)
}
// output
0
go tool compile -S
0x0024 00036 (make1_test.go:14) PCDATA $0, $1
0x0024 00036 (make1_test.go:14) PCDATA $1, $0
0x0024 00036 (make1_test.go:14) LEAQ type."".Stu(SB), AX
0x002b 00043 (make1_test.go:14) PCDATA $0, $0
0x002b 00043 (make1_test.go:14) MOVQ AX, (SP)
0x002f 00047 (make1_test.go:14) CALL runtime.newobject(SB)
0x0034 00052 (make1_test.go:14) PCDATA $0, $1
0x0034 00052 (make1_test.go:14) MOVQ 8(SP), AX
It calls runtime.newobject(SB).
5.2. make
func TestMake(t *testing.T) {
fmt.Println(makeSlice())
}
func makeSlice() []int {
return make([]int, 0)
}
go tool compile -S
0x002f 00047 (make1_test.go:13) PCDATA $0, $0
0x002f 00047 (make1_test.go:13) MOVQ AX, (SP)
0x0033 00051 (make1_test.go:13) XORPS X0, X0
0x0036 00054 (make1_test.go:13) MOVUPS X0, 8(SP)
0x003b 00059 (make1_test.go:13) CALL runtime.makeslice(SB)
0x0040 00064 (make1_test.go:13) PCDATA $0, $1
0x0040 00064 (make1_test.go:13) MOVQ 24(SP), AX
It calls runtime.makeslice(SB).
Discussion
Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub